#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
System Integration Script
Unifies system components, resolves module conflicts, and ensures system operation
"""

import os
import sys
import logging
import shutil
from pathlib import Path

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("integration.log"),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger("system_integration")

def backup_file(file_path):
    """Backup file"""
    if os.path.exists(file_path):
        backup_path = f"{file_path}.integration_backup"
        shutil.copy2(file_path, backup_path)
        logger.info(f"Backed up file: {file_path} -> {backup_path}")
        return True
    return False

def integrate_video_processing():
    """Integrate video processing logic"""
    logger.info("Integrating video processing logic...")
    
    # Define file paths
    video_processor_path = os.path.join("video_processing", "video_processor.py")
    main_app_path = "main_app.py"
    
    # Backup files
    backup_file(video_processor_path)
    backup_file(main_app_path)
    
    # Create unified video processor module
    new_video_processor_content = '''#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Unified Video Processor Module
Handles video frames and provides unified video processing interface
"""

import logging
import time
import threading
import numpy as np
from typing import Dict, List, Tuple, Optional, Any

# Configure logging
logger = logging.getLogger("video_processing.video_processor")

class VideoProcessor:
    """Unified Video Processor Class"""
    
    def __init__(self, camera_manager, frame_processor, detection_engine, analysis_manager, alert_manager):
        """Initialize video processor
        
        Args:
            camera_manager: Camera manager instance
            frame_processor: Frame processor instance
            detection_engine: Detection engine instance
            analysis_manager: Behavior analysis manager instance
            alert_manager: Alert manager instance
        """
        self.camera_manager = camera_manager
        self.frame_processor = frame_processor
        self.detection_engine = detection_engine
        self.analysis_manager = analysis_manager
        self.alert_manager = alert_manager
        self.stop_event = threading.Event()
        self.error_count = 0  # Error count
        self.last_error_reset_time = time.time()  # Last error reset time
    
    def _process_loop(self):
        """Video processing main loop"""
        logger.info("Video processing loop started")
        
        while not self.stop_event.is_set():
            try:
                # Check and reset error count - Trigger warning and recovery when error rate is too high
                current_time = time.time()
                if current_time - self.last_error_reset_time > 60:  # Reset every minute
                    self.error_count = 0
                    self.last_error_reset_time = current_time
                
                # Get active camera
                active_camera = self.camera_manager.get_active_camera()
                active_camera_name = self.camera_manager.get_active_camera_name()
                
                if active_camera and active_camera_name:
                    camera_id = active_camera_name
                    camera = active_camera
                    try:
                        # Get frame
                        ret, frame = camera.read()
                        if not ret:
                            logger.warning(f"Camera {camera_id} read failed")
                            self.error_count += 1
                            continue
                        
                        # Preprocess frame
                        processed_frame = self.frame_processor.preprocess(frame, camera_id)
                        
                        # Object detection
                        detections = self.detection_engine.detect(processed_frame)
                        
                        # Object tracking
                        tracked_objects = self.detection_engine.track(detections, processed_frame)
                        
                        # Behavior analysis
                        analysis_results = self.analysis_manager.analyze_frame(
                            camera_id, 
                            processed_frame, 
                            tracked_objects,
                            detections
                        )
                        
                        # Process violations
                        for violation in analysis_results.get('violations', []):
                            # Generate alert
                            alert_info = {
                                'type': violation['type'],
                                'camera_id': camera_id,
                                'location': camera.get_location(),
                                'message': violation['message'],
                                'metadata': violation
                            }
                            self.alert_manager.create_alert(**alert_info)
                        
                        # Postprocess frame (draw results)
                        output_frame = self.frame_processor.postprocess(
                            processed_frame,
                            tracked_objects,
                            analysis_results
                        )
                        
                        # Update camera's current frame
                        camera.set_current_frame(output_frame)
                        
                    except Exception as e:
                        logger.error(f"Processing frame from camera {camera_id} failed: {str(e)}")
                        self.error_count += 1
                
                # Control processing frequency
                time.sleep(0.01)
                
            except Exception as e:
                logger.error(f"Video processing loop exception: {str(e)}")
                self.error_count += 1
                time.sleep(1)  # Prevent frequent error logs
    
    def start_processing(self):
        """Start video processing"""
        try:
            # Start processing thread
            self.process_thread = threading.Thread(target=self._process_loop)
            self.process_thread.daemon = True
            self.process_thread.start()
            logger.info("Video processing started")
            return True
        except Exception as e:
            logger.error(f"Starting video processing failed: {str(e)}")
            return False
    
    def stop_processing(self):
        """Stop video processing"""
        try:
            self.stop_event.set()
            if hasattr(self, 'process_thread'):
                self.process_thread.join(timeout=5.0)
            logger.info("Video processing stopped")
            return True
        except Exception as e:
            logger.error(f"Stopping video processing failed: {str(e)}")
            return False
    
    def get_error_count(self):
        """Get error count"""
        return self.error_count
    
    def get_status(self):
        """Get processor status"""
        return {
            'is_running': self.process_thread.is_alive() if hasattr(self, 'process_thread') else False,
            'error_count': self.error_count,
            'active_camera': self.camera_manager.get_active_camera_name()
        }
'''
    
    # Write new video processor module
    with open(video_processor_path, 'w', encoding='utf-8') as f:
        f.write(new_video_processor_content)
    logger.info(f"Created unified video processor module: {video_processor_path}")
    
    # Update main_app.py to use the new video processor
    with open(main_app_path, 'r', encoding='utf-8') as f:
        main_app_content = f.read()
    
    # Add import
    if 'from video_processing.video_processor import VideoProcessor' not in main_app_content:
        import_lines = """
# Import core modules
from video_processing import camera_manager, frame_processor
from video_processing.video_processor import VideoProcessor"""
        main_app_content = main_app_content.replace(
            "# Import core modules\nfrom video_processing import camera_manager, frame_processor",
            import_lines.strip()
        )
    
    # Modify YOLOApplySystem class to remove built-in _video_processing_loop and use unified VideoProcessor
    if '_video_processing_loop' in main_app_content and 'self.video_processor' not in main_app_content:
        # Remove _video_processing_loop method
        start_index = main_app_content.find('def _video_processing_loop')
        end_index = main_app_content.find('def start_api_server')
        if start_index != -1 and end_index != -1:
            # Replace with code to initialize VideoProcessor
            new_code = '''    def initialize_components(self):
        """Initialize components"""
        try:
            logger.info("Initializing system components...")
            
            # Database service initialized automatically during instantiation
            logger.info("Database service initialized successfully")
            
            # Camera manager initialized automatically during instantiation
            logger.info("Camera manager initialized successfully")
            
            # Frame processor initialized automatically during instantiation
            logger.info("Frame processor initialized successfully")
            
            # Initialize detection engine (simulation mode to avoid model file dependency)
            detection_config = self.config.get('detection', {})
            self.detection_engine = DetectionEngine()
            try:
                if self.detection_engine.initialize(detection_config):
                    logger.info("Detection engine initialized successfully")
                else:
                    logger.warning("Detection engine initialization failed, but system will continue in simulation mode")
            except Exception as e:
                logger.warning(f"Detection engine initialization exception: {str(e)}, system will continue in simulation mode")
            
            # Behavior analysis manager initialized automatically during instantiation
            logger.info("Behavior analysis manager initialized successfully")
            
            # Alert manager initialized automatically during instantiation
            logger.info("Alert manager initialized successfully")
            
            # Notification service initialized automatically during instantiation
            logger.info("Notification service initialized successfully")
            
            # API service initialized automatically during instantiation
            logger.info("API service initialized successfully")
            
            # Initialize unified video processor
            self.video_processor = VideoProcessor(
                camera_manager=self.camera_manager,
                frame_processor=self.frame_processor,
                detection_engine=self.detection_engine,
                analysis_manager=self.analysis_manager,
                alert_manager=self.alert_manager
            )
            logger.info("Unified video processor initialized successfully")
            
            return True
            
        except Exception as e:
            logger.error(f"Initializing components failed: {str(e)}")
            return False

    def start_video_processing(self):
        """Start video processing thread"""
        try:
            # Start all cameras
            # Use list_cameras() method instead of non-existent get_all_cameras()
            cameras = self.camera_manager.list_cameras()
            for camera_id in cameras:
                if not self.camera_manager.start_camera(camera_id):
                    logger.error(f"Starting camera {camera_id} failed")
                else:
                    logger.info(f"Camera {camera_id} started successfully")
            
            # Use unified video processor to start processing
            if hasattr(self, 'video_processor'):
                if self.video_processor.start_processing():
                    logger.info("Video processing started through unified processor")
                    return True
                else:
                    logger.error("Starting video processing through unified processor failed")
                    return False
            else:
                logger.error("Video processor not initialized")
                return False
                
        except Exception as e:
            logger.error(f"Starting video processing failed: {str(e)}")
            return False

    def stop(self):
        """Stop the system"""
        try:
            logger.info("Stopping system...")
            self.is_running = False
            self.stop_event.set()
            
            # Stop video processing
            if hasattr(self, 'video_processor'):
                self.video_processor.stop_processing()
            
            # Stop all threads
            for thread in self.threads:
                if thread.is_alive():
                    thread.join(timeout=3.0)
            
            # Stop all cameras
            cameras = self.camera_manager.list_cameras()
            for camera_id in cameras:
                self.camera_manager.stop_camera(camera_id)
            
            logger.info("System stopped")
            return True
        except Exception as e:
            logger.error(f"Stopping system failed: {str(e)}")
            return False

    def start_api_server(self):'''
            main_app_content = main_app_content[:start_index] + new_code + main_app_content[end_index:]
    
    # Write updated main_app.py
    with open(main_app_path, 'w', encoding='utf-8') as f:
        f.write(main_app_content)
    logger.info(f"Updated main_app.py to use unified video processor")

def check_and_fix_imports():
    """Check and fix import issues"""
    logger.info("Checking and fixing import issues...")
    
    # Check video_processing package __init__.py
    init_file = os.path.join("video_processing", "__init__.py")
    if not os.path.exists(init_file):
        with open(init_file, 'w', encoding='utf-8') as f:
            f.write("""# Video Processing Package
from .camera_manager import CameraManager
from .frame_processor import FrameProcessor, get_frame_processor
from .video_processor import VideoProcessor

__all__ = ['CameraManager', 'FrameProcessor', 'get_frame_processor', 'VideoProcessor']""")
        logger.info(f"Created video_processing package __init__.py: {init_file}")

def main():
    """Main function"""
    logger.info("Starting system integration...")
    
    # Check project structure
    required_dirs = ["video_processing", "models", "config", "data"]
    for dir_name in required_dirs:
        if not os.path.exists(dir_name):
            os.makedirs(dir_name)
            logger.info(f"Created required directory: {dir_name}")
    
    # Integrate video processing logic
    integrate_video_processing()
    
    # Check and fix import issues
    check_and_fix_imports()
    
    # Validate integration result
    logger.info("Validating integration result...")
    
    # Check if key files exist
    key_files = [
        os.path.join("video_processing", "video_processor.py"),
        os.path.join("video_processing", "camera_manager.py"),
        os.path.join("video_processing", "frame_processor.py"),
        "main_app.py",
        "detection_engine.py"
    ]
    
    all_files_exist = True
    for file_path in key_files:
        if not os.path.exists(file_path):
            logger.error(f"Key file does not exist: {file_path}")
            all_files_exist = False
        else:
            logger.info(f"Key file exists: {file_path}")
    
    if all_files_exist:
        logger.info("System integration completed!")
        logger.info("You can now run the main application.")
    else:
        logger.error("System integration failed, some key files are missing.")

if __name__ == "__main__":
    main()